/******************************************************************************
 * * contact_delete.c - implementation of contact delete functions
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/
#include "contact_global.h"

/**
 * Callback function for additional actions after Creating Contacts_Delete_Quit interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Delete_Quit_OnCreate(VOID *Ctrl)
{
    UI_Status_Desc_t *StatusDesc = (UI_Status_Desc_t *)Ctrl;
    lv_obj_t         *Label      = StatusDesc->ContLabel.Label;
    INT8             *Text;
    INT8             *Output;
    UINT8            Len;

    if (1 < g_ContactsMng.ContactOper.MarkNum)
    {
        Text = (INT8 *)lv_lang_get_text(PHONE_TEXT_ID_CONTACTS_NOT_DELETED);
    }
    else
    {
        Text = (INT8 *)lv_lang_get_text(PHONE_TEXT_ID_CONTACT_NOT_DELETED);
    }

    Len    = 4 + strlen(Text) + 1;
    Output = (INT8 *)Hal_Mem_Alloc(Len);
    sprintf(Output, "%d%s", g_ContactsMng.ContactOper.MarkNum, Text);
    lv_label_set_text(Label, Output);
    Hal_Mem_Free(Output);

    Contacts_Status_Interface_Timer_Start(Contacts_Timeout_Back_To_Prev_Interface);
}

/**
 * Callback function for restoring state on Contacts_Delete_Quit interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Delete_Quit_OnRestoreState(VOID *Ctrl)
{
    UI_Status_Desc_t *StatusDesc = (UI_Status_Desc_t *)Ctrl;
    lv_obj_t         *Label      = StatusDesc->ContLabel.Label;
    INT8             *Text;
    INT8             *Output;
    UINT8            Len;

    g_ContactsMng.InterfaceCtrl.Ctrl        = Ctrl;
    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_DELETE_QUIT;

    if (1 < g_ContactsMng.ContactOper.MarkNum)
    {
        Text = (INT8 *)lv_lang_get_text(PHONE_TEXT_ID_CONTACTS_NOT_DELETED);
    }
    else
    {
        Text = (INT8 *)lv_lang_get_text(PHONE_TEXT_ID_CONTACT_NOT_DELETED);
    }

    Len    = 4 + strlen(Text) + 1;
    Output = (INT8 *)Hal_Mem_Alloc(Len);
    sprintf(Output, "%d%s", g_ContactsMng.ContactOper.MarkNum, Text);
    lv_label_set_text(Label, Output);
    Hal_Mem_Free(Output);
}

/**
 * Create Contacts_Delete_Quit interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Delete_Quit(VOID)
{
    UI_Status_Desc_t *StatusDesc;
    Nav_Func_List_t  FuncList;

    StatusDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    Hal_Mem_Set(StatusDesc, 0, sizeof(UI_Status_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_DELETE_QUIT;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)StatusDesc;

    StatusDesc->ContLabel.TxtId      = PHONE_TEXT_ID_DELETED;
    StatusDesc->ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    StatusDesc->ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    StatusDesc->ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    StatusDesc->ContImg.Img  = SYMBOL_CHECKED;
    StatusDesc->ContImgAlign = LV_ALIGN_IN_TOP_RIGHT;

    StatusDesc->KeyFunc = Contacts_Status_Interface_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Status_Create;
    FuncList.OnCreate       = Contacts_Delete_Quit_OnCreate;
    FuncList.OnRestoreState = Contacts_Delete_Quit_OnRestoreState;
    FuncList.OnDestroy      = Contacts_Interface_OnDestroy;

    Nav_Backward_And_Forward(ACT_ID_ANY, ACT_ID_CONTACTS, ACT_ID_CONTACTS_DELETE_QUIT, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
}

/**
 * Create Contacts_Deleted interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Deleted(VOID)
{
    UI_Status_Desc_t *StatusDesc;
    Nav_Func_List_t  FuncList;

    StatusDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    Hal_Mem_Set(StatusDesc, 0, sizeof(UI_Status_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_DELETED;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)StatusDesc;

    StatusDesc->ContLabel.TxtId      = PHONE_TEXT_ID_DELETED;
    StatusDesc->ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    StatusDesc->ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    StatusDesc->ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    StatusDesc->ContImg.Img  = SYMBOL_CHECKED;
    StatusDesc->ContImgAlign = LV_ALIGN_IN_TOP_RIGHT;

    StatusDesc->KeyFunc = Contacts_Status_Interface_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow    = UI_Status_Create;
    FuncList.OnCreate  = Contacts_Status_Interface_OnCreate;
    FuncList.OnDestroy = Contacts_Interface_OnDestroy;

    Nav_Backward_And_Forward(ACT_ID_ANY, ACT_ID_CONTACTS, ACT_ID_CONTACTS_DELETED, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
}

/**
 * Callback function for handling key pressed on Contacts_Deleting interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Contacts_Deleting_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT: // quit
            if (0 < g_ContactsMng.ContactOper.MarkNum)
            {
                g_ContactsMng.ContactOper.ProcQuit = TRUE;
                Contacts_Create_Contacts_Delete_Quit();
            }
            break;

        case KEY_END:
            g_ContactsMng.ContactOper.ProcQuit = TRUE;
            Nav_Home(ACT_ID_ANY);
            break;

        default:
            break;
        } /* switch */
    }

    return(1);
} /* Contacts_Deleting_Key_Cb */

/**
 * Callback function for saving state on Contacts_Contacts_Deleting interface before forward to another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Contacts_Deleting_OnSaveState(VOID *Ctrl)
{
    g_ContactsMng.InterfaceCtrl.InterfaceId = 0xFFFF;
}

/**
 * Callback function for restoring state on Contacts_Deleting interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Deleting_OnRestoreState(VOID *Ctrl)
{
    g_ContactsMng.InterfaceCtrl.Ctrl        = Ctrl;
    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_DELETING;
}

/**
 * Create Contacts_Deleting interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Deleting(VOID)
{
    UI_Normal_NoTitle_Desc_t *Interface;
    Nav_Func_List_t          FuncList;

    Interface = (UI_Normal_NoTitle_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_NoTitle_Desc_t));
    Hal_Mem_Set(Interface, 0, sizeof(UI_Normal_NoTitle_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_DELETING;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)Interface;

    Interface->ContenCont.ContLabel.TxtId      = PHONE_TEXT_ID_DELETING;
    Interface->ContenCont.ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    Interface->ContenCont.ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    Interface->ContenCont.ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    Interface->ContenCont.ContImgAlign     = LV_ALIGN_IN_BOTTOM_LEFT;
    Interface->ContenCont.ContImg.ImgAlign = LV_ALIGN_IN_BOTTOM_LEFT;
    Interface->ContenCont.ContImg.Img      = IMG_PROGRESS_BAR;

    Interface->ButtonBar.ButtonL.Valid = FALSE;
    Interface->ButtonBar.ButtonM.Valid = FALSE;
    Interface->ButtonBar.ButtonR.Valid = TRUE;
    Interface->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_QUIT;

    Interface->KeyFunc = Contacts_Deleting_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_NoTitle_Create;
    FuncList.OnRestoreState = Contacts_Deleting_OnRestoreState;
    FuncList.OnSaveState    = Contacts_Contacts_Deleting_OnSaveState;
    FuncList.OnDestroy      = Contacts_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CONTACTS_DELETING, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
}

/**
 * Deleting Process end
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Process_Delete_End_Handle(VOID)
{
    printf("%s: MarkNum %d, ProcQuit %d\n",
           __FUNCTION__, g_ContactsMng.ContactOper.MarkNum, g_ContactsMng.ContactOper.ProcQuit);

    g_ContactsMng.ContactOper.Action = CONTACTS_ACTION_NULL;

    if (NULL == Nav_Get_Param(ACT_ID_CONTACTS))
    {
        printf("%s: not in contacts\n", __FUNCTION__);
        g_ContactsMng.ContactOper.MarkNum = 0;
        g_ContactsMng.ContactOper.ProcQuit = FALSE;
        return;
    }

    Contacts_Reset_Contacts_Interface();

    if (Nav_Get_Top() != g_ContactsMng.InterfaceCtrl.InterfaceId)
    {   /* Contacts_Deleting interface was covered by other interface */
        Nav_Forward(ACT_ID_CONTACTS_DELETING, ACT_ID_CONTACTS, NULL, NULL);
    }
    else if (0 == g_ContactsMng.ContactOper.MarkNum)
    {
        Contacts_Create_Contacts_Deleted();
    }
    else
    {
        g_ContactsMng.ContactOper.ProcQuit = FALSE;
    }
}

/**
 * Process for deleting multiple contacts
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Process_Delete_Multiple_Contacts(VOID)
{
    Contacts_List_t *Contact;
    Contacts_List_t *ContactTemp;
    lv_ll_t         *ContactsList;
    UINT16          Index;
    UINT8           Bit;
    UINT8           Memory;
    UINT8           NvBitmap;

    ContactsList = Contacts_Get_Contacts_Operation_List(NULL);

    if (NULL == g_ContactsMng.InterfaceCtrl.Focus)
    {
        g_ContactsMng.InterfaceCtrl.Focus = _lv_ll_get_head(ContactsList);
    }

    while (NULL != g_ContactsMng.InterfaceCtrl.Focus)
    {
        Contact                           = g_ContactsMng.InterfaceCtrl.Focus;
        g_ContactsMng.InterfaceCtrl.Focus = _lv_ll_get_next(ContactsList, Contact);

        if (TRUE == Contact->ContactInfo->MarkFlg)
        {
            Memory = Contacts_Get_Contact_Memory(Contact->ContactInfo->MemoryAndIndex);
            Index  = Contacts_Get_Contact_Index(Contact->ContactInfo->MemoryAndIndex);

            g_ContactsMng.ContactOper.MarkNum--;
            g_ContactsMng.ContactsCount--;

            Contacts_Speed_Dials_Update_Contact(Contact->ContactInfo, NULL, NULL);

            _lv_ll_remove(ContactsList, Contact);

            if (CONTACTS_MEMSEL_ALL != g_ContactsMng.ContactsMemSel.MemSel)
            {
                g_ContactsMng.ContactsMemSel.ContactsCount--;

                /* delete contact from ContactsList */
                while (NULL != g_ContactsMng.InterfaceCtrl.FocusContact)
                {
                    ContactTemp = g_ContactsMng.InterfaceCtrl.FocusContact;
                    g_ContactsMng.InterfaceCtrl.FocusContact = _lv_ll_get_next(&g_ContactsMng.ContactsList, ContactTemp);

                    if (Contact->ContactInfo == ContactTemp->ContactInfo)
                    {
                        _lv_ll_remove(&g_ContactsMng.ContactsList, ContactTemp);
                        Hal_Mem_Free(ContactTemp);
                        break;
                    }
                }
            }

            Hal_Mem_Free(Contact->ContactInfo);
            Hal_Mem_Free(Contact);

            g_ContactsMng.PhkStatus[Memory].Used--;
            if (CONTACTS_MEMORY_PHONE == Memory)
            {
                /* delete the marked contact from NVM */
                Bit   = Index % 8;
                Index = Index / 8;
                printf("%s: index %d, bit %d\n", __FUNCTION__, Index, Bit);
                if (1 != UI_NV_Read_Req(NV_SECTION_UI_CONTACTS_BITMAP, Index, 1, &NvBitmap))
                {
                    /* error */
                    return;
                }
                NvBitmap &= ~(0x01 << Bit);
                if (1 != UI_NV_Write_Req(NV_SECTION_UI_CONTACTS_BITMAP, Index, 1, &NvBitmap))
                {
                    /* error */
                    return;
                }

                if ((0 == g_ContactsMng.ContactOper.MarkNum)
                    || g_ContactsMng.ContactOper.ProcQuit)
                {
                    Contacts_Process_Delete_End_Handle();
                    break;
                }
            }
            else
            {
                Contacts_Send_Write_Phonebook_Req(Memory, NULL, NULL, Index);
                break;
            }
        }
    }
} /* Contacts_Process_Delete_Multiple_Contacts */

/**
 * Security code check confirm for contacts delete operation
 * param (in) Result: SETTING_RESULT
 * return  VOID
 */
VOID Contacts_Delete_Check_Security_Cnf(SETTING_RESULT Result)
{
    if (SETTING_OK != Result)
    {
        return;
    }

    g_ContactsMng.ContactOper.Action = CONTACTS_ACTION_DELETE;

    Contacts_Create_Contacts_Deleting();

    if (CONTACTS_MEMSEL_ALL != g_ContactsMng.ContactsMemSel.MemSel)
    {
        /* get the head of contacts list to start to perform delete operation  */
        g_ContactsMng.InterfaceCtrl.FocusContact = _lv_ll_get_head(&g_ContactsMng.ContactsList);
    }

    g_ContactsMng.InterfaceCtrl.Focus = NULL;
    Contacts_Process_Delete_Multiple_Contacts();
}

/**
 * Callback function for handling key pressed on Contacts_Delete_Ready interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Contacts_Delete_Ready_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_OK:
            Setting_Check_Security_Req(Contacts_Delete_Check_Security_Cnf);
            break;

        default:
            break;
        } /* switch */
    }

    return(1);
} /* Contacts_Delete_Ready_Key_Cb */

/**
 * Callback function for additional actions after Creating Contacts_Delete_Ready interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Delete_Ready_OnCreate(VOID *Ctrl)
{
    UI_Normal_NoTitle_Desc_t *Interface = (UI_Normal_NoTitle_Desc_t *)Ctrl;
    lv_obj_t                 *Label     = Interface->ContenCont.ContLabel.Label;
    INT8                     *Text1;
    INT8                     *Text2;
    UINT8                    Len;
    INT8                     *Output;

    Text1 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_DELETE));
    if (1 < g_ContactsMng.ContactOper.MarkNum)
    {
        Text2 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_CONTACTS_Q));
    }
    else
    {
        Text2 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_CONTACT_Q));
    }

    Len    = strlen(Text1) + 5 + strlen(Text2) + 1;
    Output = (INT8 *)Hal_Mem_Alloc(Len);
    sprintf(Output, "%s %d%s", Text1, g_ContactsMng.ContactOper.MarkNum, Text2);
    lv_label_set_text(Label, Output);
    Hal_Mem_Free(Output);
}

/**
 * Callback function for restoring state on Contacts_Delete_Ready interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Delete_Ready_OnRestoreState(VOID *Ctrl)
{
    UI_Normal_NoTitle_Desc_t *Interface = (UI_Normal_NoTitle_Desc_t *)Ctrl;
    lv_obj_t                 *Label     = Interface->ContenCont.ContLabel.Label;
    INT8                     *Text1;
    INT8                     *Text2;
    UINT8                    Len;
    INT8                     *Output;

    g_ContactsMng.InterfaceCtrl.Ctrl        = Ctrl;
    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_DELETE_READY;

    Text1 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_DELETE));
    if (1 < g_ContactsMng.ContactOper.MarkNum)
    {
        Text2 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_CONTACTS_Q));
    }
    else
    {
        Text2 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_CONTACT_Q));
    }

    Len    = strlen(Text1) + 4 + strlen(Text2) + 1;
    Output = (INT8 *)Hal_Mem_Alloc(Len);
    sprintf(Output, "%s%d%s", Text1, g_ContactsMng.ContactOper.MarkNum, Text2);
    lv_label_set_text(Label, Output);
    Hal_Mem_Free(Output);
}

/**
 * Create Contacts_Delete_Ready interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Delete_Ready(VOID)
{
    UI_Normal_NoTitle_Desc_t *Interface;
    Nav_Func_List_t          FuncList;

    Interface = (UI_Normal_NoTitle_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_NoTitle_Desc_t));
    Hal_Mem_Set(Interface, 0, sizeof(UI_Normal_NoTitle_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_DELETE_READY;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)Interface;

    Interface->ContenCont.ContLabel.TxtId      = LV_LANG_TXT_ID_NONE;
    Interface->ContenCont.ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    Interface->ContenCont.ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    Interface->ContenCont.ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    Interface->ButtonBar.ButtonL.Valid = FALSE;

    Interface->ButtonBar.ButtonM.Valid = TRUE;
    Interface->ButtonBar.ButtonM.TxtId = PHONE_TEXT_ID_OK;

    Interface->ButtonBar.ButtonR.Valid = TRUE;
    Interface->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;

    Interface->KeyFunc = Contacts_Delete_Ready_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_NoTitle_Create;
    FuncList.OnCreate       = Contacts_Delete_Ready_OnCreate;
    FuncList.OnRestoreState = Contacts_Delete_Ready_OnRestoreState;
    FuncList.OnDestroy      = Contacts_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CONTACTS_DELETE_READY, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
}

/**
 * Callback function for handling key pressed on Contacts_Delete interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Contacts_Delete_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UINT8 Ret = 1;

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_UP:
        case KEY_LEFT:
        case KEY_DOWN:
        case KEY_RIGHT:
            Ret = Contacts_Com_Select_Multi_Press_Direction_Key(Key_Val);
            break;

        case KEY_OK:
            Ret = 0; // call the default key function
            break;

        case KEY_SOFTLEFT: // delete marked contacts
            if (0 != g_ContactsMng.ContactOper.MarkNum)
            {
                Contacts_Create_Contacts_Delete_Ready();
            }
            break;

        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
} /* Contacts_Delete_Key_Cb */

/**
 * Create Contacts_Delete interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Delete(VOID)
{
    Contacts_Com_Create_Select_Multi_Contacts(ACT_ID_CONTACTS_DELETE, Contacts_Delete_Key_Cb);
}
